package cn.ztuo.bitrade.waiting;

import cn.ztuo.bitrade.entity.ContractOrder;
import cn.ztuo.bitrade.entity.ContractOrderDirection;
import cn.ztuo.bitrade.entity.ContractOrderType;
import cn.ztuo.bitrade.entity.MergeOrder;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.*;

/**
 * @description: WaitingOrder
 * @author: fiwork.net
 * @create: 2019/04/27 15:20
 */
@Slf4j
@Data
public class WaitingOrder {

    private String symbol;
    /**
     *止盈止损买入 按照触发价从小到大排序 小价格在前 大价格在后(价格升高)
     */
    private TreeMap<BigDecimal, MergeOrder> buyTriggerPriceQueue;
    /**
     * 卖出限价订单链表，价格从低到高排列(从大到小)(价格下降)
     */
    private TreeMap<BigDecimal, MergeOrder> sellTriggerPriceQueue;

    /**
     * 是否初始化完毕
     */
    private boolean ready = false;

    public WaitingOrder(String symbol){
        this.symbol=symbol;
    }

    /**
     * 初始化交易线程
     */
    public void initialize(){
        log.info("init waiting for symbol {}",symbol);
        //买单队列价格降序排列
        buyTriggerPriceQueue = new TreeMap<>(Comparator.naturalOrder());
        //卖单队列价格升序排列
        sellTriggerPriceQueue = new TreeMap<>(Comparator.reverseOrder());
    }


    /**
     * 增加限价订单到队列，买入单按从价格高到低排，卖出单按价格从低到高排
     * @param contractOrder
     */
    public void addWaitingOrder(ContractOrder contractOrder){
        if(contractOrder.getType() != ContractOrderType.CHECK_FULL_STOP&&contractOrder.getType() != ContractOrderType.PLAN_PRICE){
            return ;
        }
        log.info("addWaitingOrder,orderId = {}", contractOrder.getOrderId());
        TreeMap<BigDecimal, MergeOrder> list;
        String name  ;
        if((contractOrder.getDirection() == ContractOrderDirection.BUY&&contractOrder.getStopType()==2)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==0)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==1)){
            list = buyTriggerPriceQueue;
            name="buyTriggerPriceQueue";
        }else {
            list = sellTriggerPriceQueue;
            name="sellTriggerPriceQueue";
        }
        synchronized (list) {
            MergeOrder mergeOrder = list.get(contractOrder.getTriggerPrice());
            if(mergeOrder == null){
                mergeOrder = new MergeOrder();
                mergeOrder.add(contractOrder);
                list.put(contractOrder.getTriggerPrice(), mergeOrder);
                log.info(name+"中无此价格新增价格梯度={}",list);
            }else {
                mergeOrder.add(contractOrder);
                log.info(name+"中有此价格新增价格梯度={}",list);
            }
        }
    }

    public void dealWaitingOrder(List<ContractOrder> contractOrders){
        for (ContractOrder order :contractOrders){
            dealOrder(order);
        }

    }

    public void dealOrder(ContractOrder order) {
        if(order.getType() != ContractOrderType.CHECK_FULL_STOP&&order.getType() != ContractOrderType.PLAN_PRICE){
            return ;
        }
        log.info("waiting order={}",order);
        if(!symbol.equalsIgnoreCase(order.getSymbol())){
            log.info("unsupported symbol={},coin={},base={}",order.getSymbol(), order.getCoinSymbol(), order.getBaseSymbol());
            return ;
        }
        if(order.getAmount().compareTo(BigDecimal.ZERO) <=0 || order.getAmount().subtract(order.getTradedAmount()).compareTo(BigDecimal.ZERO)<=0){
            return ;
        }
        addWaitingOrder(order);
    }

    public ContractOrder findWaitingOrder(ContractOrder contractOrder, ContractOrderDirection direction) {
//        TreeMap<BigDecimal, MergeOrder> list;
//        if(direction==ContractOrderDirection.SELL){
//            list = sellTriggerPriceQueue;
//        }else {
//            list = buyTriggerPriceQueue;
//        }
        String orderId = contractOrder.getOrderId();
        TreeMap<BigDecimal, MergeOrder> list;
        if((contractOrder.getDirection() == ContractOrderDirection.BUY&&contractOrder.getStopType()==2)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==0)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==1)){
            list = buyTriggerPriceQueue;
        }else {
            list = sellTriggerPriceQueue;
        }
        synchronized (list) {
            Iterator<Map.Entry<BigDecimal, MergeOrder>> mergeOrderIterator = list.entrySet().iterator();
            while (mergeOrderIterator.hasNext()) {
                Map.Entry<BigDecimal, MergeOrder> entry = mergeOrderIterator.next();
                MergeOrder mergeOrder = entry.getValue();
                Iterator<ContractOrder> orderIterator = mergeOrder.iterator();
                while ((orderIterator.hasNext())) {
                    ContractOrder order = orderIterator.next();
                    if (order.getOrderId().equalsIgnoreCase(orderId)) {
                        log.info("堆栈中有该信息");
                        return order;
                    }
                }
            }
        }
        return null;
    }

    public ContractOrder cancel(ContractOrder contractOrder) {
        log.info("取消止盈止损队列order={}",contractOrder);
        if(contractOrder.getType()!=ContractOrderType.CHECK_FULL_STOP&&contractOrder.getType()!=ContractOrderType.PLAN_PRICE){
            log.info("类型不对");
            return null;
        }
//        TreeMap<BigDecimal, MergeOrder> list;
//        if(contractOrder.getDirection()==ContractOrderDirection.BUY){
//            list = buyTriggerPriceQueue;
//        }else {
//            list = sellTriggerPriceQueue;
//        }
        TreeMap<BigDecimal, MergeOrder> list;
        if((contractOrder.getDirection() == ContractOrderDirection.BUY&&contractOrder.getStopType()==2)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==0)
                ||(contractOrder.getDirection() == ContractOrderDirection.SELL&&contractOrder.getStopType()==1)){
            list = buyTriggerPriceQueue;
        }else {
            list = sellTriggerPriceQueue;
        }
        synchronized (list) {
            MergeOrder mergeOrder = list.get(contractOrder.getTriggerPrice());
            Iterator<ContractOrder> orderIterator = mergeOrder.iterator();
            if (orderIterator != null) {
                while (orderIterator.hasNext()) {
                    ContractOrder order = orderIterator.next();
                    if (order.getOrderId().equalsIgnoreCase(contractOrder.getOrderId())) {
                        orderIterator.remove();
                        if (mergeOrder.size() == 0) {
                            list.remove(contractOrder.getTriggerPrice());
                        }
                        log.info("移除该订单+{}",order.getOrderId());
                        return order;
                    }
                }
            }
        }
        log.info("队列没有");
        return null;
    }
}
